/* BufferredStreamFile.h
 * 
 *  Author          : Alexander J. Yee
 *  Date Created    : 03/19/2018
 *  Last Modified   : 07/03/2019
 * 
 *      Convenience wrappers around RawFile to produce reader/writer file streams.
 * 
 */

#pragma once
#ifndef ymp_FileIO_BufferredStreamFile_H
#define ymp_FileIO_BufferredStreamFile_H
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//  Dependencies
#include "PublicLibs/BasicLibs/Memory/SmartBuffer.h"
#include "RawFile/RawFile.h"
namespace ymp{
namespace FileIO{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class BufferedReader{
public:
    BufferedReader(RawFile& file);

    const std::string& path() const;
    ufL_t offset() const;

    char next(){
        if (m_buffer_offset == m_buffer_end){
            refill();
        }
        return m_buffer[m_buffer_offset++];
    }

private:
    void refill();

private:
//    alignas(FILE_ALIGNMENT) char m_buffer[FILE_ALIGNMENT];
    upL_t m_block;
    SmartBuffer<char> m_buffer;
    upL_t m_buffer_offset;
    upL_t m_buffer_end;
    ufL_t m_file_offset;
    RawFile& m_file;
};
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class BufferedWriter{
public:
    BufferedWriter(RawFile& file);
    ~BufferedWriter();

    const std::string& path() const;
    ufL_t offset() const;

    void push(char ch){
        if (m_buffer_offset == m_block){
            refill();
        }
        m_buffer[m_buffer_offset++] = ch;
    }
    void push(const char* buffer, upL_t bytes);

private:
    void flush();
    void refill();

private:
    upL_t m_block;
    SmartBuffer<char> m_buffer;
    upL_t m_buffer_offset;
    ufL_t m_file_offset;
    RawFile& m_file;
};
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
}
}
#endif
